/** 
 * This File is the Basic Part of Getting The Images & Ico & Windows Title & HANDLE of the Froms.
 *
 * Not Finished
 *
 * Author: yylang1987
 * Modified @ 2008.10.18
 *
 */


//The header file get from javah
#include "extra_switcher_ExtraSwitchProcessInfoGetter.h"
#include <windows.h>

//The Method Used for Get The Sizeof the Window.
#define RECTWIDTH(rc)  ((rc).right - (rc).left)
#define RECTHEIGHT(rc) ((rc).bottom - (rc).top)

#define MAX_LENGTH_TITLE 256

//The Method to change the HBITMAP into a awt.image (jobject)
//Error existing
jobject MakeHBITMAPIntoImage(JNIEnv * env,HBITMAP hbitmap ) {
	jobject jImage;
	jclass jImageClass;
	jmethodID jMethod;
	jfieldID jField;
	BITMAP bmp;

	jintArray rgbArray;
	char *charArray;
	int *intArray;
	int w, h, index, type;
	
	GetObject(hbitmap, sizeof(BITMAP), &bmp);
	jImageClass = env->FindClass("java/awt/image/BufferedImage");
	jMethod = env->GetMethodID(jImageClass, "<init>", "(III)V");
	jField =env->GetStaticFieldID( jImageClass, "TYPE_INT_ARGB", "I");
	type = env->GetStaticIntField(jImageClass, jField);
	jImage = env->NewObject(jImageClass, jMethod, bmp.bmWidth, bmp.bmHeight, type);


	// Get the RGB byte triplets of the BITMAP
	charArray = (char *)malloc(sizeof(char) * bmp.bmHeight * bmp.bmWidth * 4);
	GetBitmapBits(hbitmap, sizeof(char) * bmp.bmHeight * bmp.bmWidth * 4, charArray);
	 
	// Allocate space to store the RGB ints and convert the RGB byte triplets to RGB ints
	intArray = (int *)malloc(sizeof(int) * bmp.bmHeight * bmp.bmWidth);
	index = 0;
	printf("Image Size:%ld, %ld\n",bmp.bmHeight, bmp.bmWidth);
	for (h = 0; h < bmp.bmHeight; ++h) {
		for (w = 0; w < bmp.bmWidth; ++w)
		{
			
			int b = *(charArray + index * 4) & 0xFF;
			int g = *(charArray + index * 4 + 1) & 0xFF;
			int r = *(charArray + index * 4 + 2) & 0xFF;
			*(intArray + index) = 0xFF000000 | (r << 16) | (g << 8) | b;
			
//printf("RBG ORI1:%8x,ORI2:%8x,ORI3:%8x,ORI1:%8x,ORI2:%8x,ORI3:%8x\n",*(charArray + index * 3), *(charArray + index * 3 + 1),*(charArray + index * 3 + 2),*(charArray + index * 3 + 3), *(charArray + index * 3 + 4),*(charArray + index * 3 + 5));
//			printf("RBG ORI1:%8x,ORI2:%8x,ORI3:%8x,CUR:%8x, B:%8x() G:%8x R:%8x\n",*(charArray + index * 3), *(charArray + index * 3 + 1),*(charArray + index * 3 + 2), *(intArray + index), b, g, r);
			++index;
		}
	}


	 
	// Create a jintArray for the C RGB ints
	rgbArray = env->NewIntArray( bmp.bmHeight * bmp.bmWidth);
	env->SetIntArrayRegion( rgbArray, 0, bmp.bmHeight * bmp.bmWidth, (jint*)intArray);
	 
	// Use BufferedImage.setRGB() to fill the image
	jMethod = env->GetMethodID( jImageClass, "setRGB", "(IIII[III)V");
	env->CallVoidMethod(jImage, jMethod, 0, 0, bmp.bmWidth, bmp.bmHeight, rgbArray, 0, bmp.bmWidth); // int scansize
	// Free stuff
	env->DeleteLocalRef( rgbArray);
	free(charArray);
	free(intArray);
	return jImage;
}

//Not Finished
jobject GetCaptionFromHWND(JNIEnv * env,HWND hwnd) {
	jobject ReturnImage;
	//Get the DC
	HDC hdc = GetWindowDC(hwnd);
	if (hdc)
	{
		//Get a MemDC
		HDC hdcMem = CreateCompatibleDC(hdc);
		if (hdcMem)
		{
			//Get the size of the DC
			RECT rc;
			GetWindowRect(hwnd, &rc);

			//Get A HBITMAP of the DC
			HBITMAP hbitmap = CreateCompatibleBitmap(hdc, RECTWIDTH(rc), RECTHEIGHT(rc));
			if (hbitmap)
			{
				//Get a MamDC with Bitmap
				SelectObject(hdcMem, hbitmap);
				//Get the caption
				PrintWindow(hwnd, hdcMem, 0);
				//Get the Image for java
				ReturnImage = MakeHBITMAPIntoImage(env, hbitmap);
				//Free Bitmap
				DeleteObject(hbitmap);
			}
			DeleteObject(hdcMem);
		}
		ReleaseDC(hwnd, hdc);
	}
	return ReturnImage;
}

jobject GetIconFromHWND(JNIEnv * env,HWND hwnd) {
	HICON WindowIco = (HICON)SendMessage(hwnd, WM_GETICON, ICON_BIG, NULL);
	HBITMAP hBitmap;
	if (WindowIco == NULL) {
		WindowIco = (HICON)SendMessage(hwnd, WM_GETICON, ICON_SMALL, NULL);
		if (WindowIco == NULL) {
			printf("NO ICON FOUND\n");
			return NULL;
		} else {
			printf("SMALL ICON FOUND\n");
		}
	}

	ICONINFO iconinfo;
	GetIconInfo(WindowIco, &iconinfo);
	hBitmap = iconinfo.hbmColor;
	
	jobject ReturnImage;
	ReturnImage = MakeHBITMAPIntoImage(env, hBitmap);
	return ReturnImage;
}

//This is the basic native function to get the infomation of froms
//Not Finished
JNIEXPORT jint JNICALL Java_extra_switcher_ExtraSwitchProcessInfoGetter_getInfoFromAPI (JNIEnv * env, jclass) {
	LONG Style;//Window Style get from the form
	TCHAR WindowTitle[MAX_LENGTH_TITLE];
	HWND HWND_Window_first = GetTopWindow(NULL);
	HWND HWND_Window_Corrent = HWND_Window_first;



	//Get The Method of the father class
	jclass jInfoGetterClass;
	jint WindowHandle;
	jstring WindowTitleString;
	jobject jImageObject;
	jobject jImageICONObject;
	jmethodID jAddDataMethodID;
	jboolean AddSuccess;//Whether it is success added

	//Get the classes used from java
	jInfoGetterClass = env->FindClass("extra/switcher/ExtraSwitchProcessInfoGetter");
	
	if (jInfoGetterClass == NULL) {//not get main class
		return 0;
	}

	//Get the method of the class
	jAddDataMethodID= env->GetStaticMethodID(jInfoGetterClass , "AddData", "(ILjava/lang/String;Ljava/awt/Image;Ljava/awt/Image;)Z");
	if (jAddDataMethodID == NULL) {//Not get the method
		return 0;
	}


	while (true) {
		//The Main While to get the Windows Infomation
		//Get Next Window
		HWND_Window_Corrent = GetNextWindow(HWND_Window_Corrent,GW_HWNDNEXT);
		if (HWND_Window_Corrent != NULL) {
			Style = GetWindowLong(HWND_Window_Corrent,GWL_STYLE);
			if ((Style & WS_VISIBLE))  {
				if (Style & WS_MINIMIZE) {
					//The Window is minimized
					//not use
					continue;
				}

				if (Style & WS_DISABLED) {
					//The Window is minimized
					//not use
					continue;
				}
				

				//Now Getting HANDLE is WindowHandle
				WindowHandle = (jint)HWND_Window_Corrent;

				//Now Getting the title;
				GetWindowText(HWND_Window_Corrent, WindowTitle, MAX_LENGTH_TITLE);

				if ((lstrcmp(WindowTitle, TEXT("Program Manager"))==0) && (Style & WS_CLIPCHILDREN)) continue;

				jsize TitleSize = (jsize)lstrlen(WindowTitle);
				WindowTitleString = env->NewString((const jchar *)WindowTitle, TitleSize);
				// WindowTitleString
		

				//Now Getting Captions
				jImageObject = GetCaptionFromHWND(env,HWND_Window_Corrent);


				//Now Getting Icons
				jImageICONObject = GetIconFromHWND(env,HWND_Window_Corrent);

				//Now Add this to the javaclass
				AddSuccess = env->CallStaticBooleanMethod(jInfoGetterClass, jAddDataMethodID, WindowHandle, WindowTitleString, jImageICONObject, jImageObject);
				if (AddSuccess == false) {
					printf("FAILED TO ADD\n");
//					return 0;
				}
			}
		} else {
			//I get Null Window, so Break the While
			break;
		}
	}
	return 1;
}